use std::{io::Read, fmt::Display};
use rusqlite::Connection;
pub struct SqliteTools {
    conn: Connection,
}
impl SqliteTools {
    pub fn builder(db_path: &str) -> SqliteTools {
        SqliteTools {
            conn: Connection::open(db_path).expect(&format!("数据库连接失败!!:{}", db_path)),
        }
    }
    pub fn tables_info(&self) -> Vec<TableInfo> {
        let mut stmt = self
            .conn
            .prepare("select * from sqlite_master where type = 'table'")
            .unwrap();
        // for name in stmt.column_names(){
        //     println!("{}",name);
        // }
        let name_id = stmt.column_index("name").expect("没有字段:name");
        let tbl_name_id = stmt.column_index("tbl_name").expect("没有字段:tbl_name");
        let sql_id = stmt.column_index("sql").expect("没有字段:sql");
        let table_infos = stmt.query_map([], |row| {
            Ok(TableInfo {
                name: row.get(name_id)?,
                tbl_name: row.get(tbl_name_id)?,
                sql: row.get(sql_id)?,
            })
        });
        let infos: Vec<_> = table_infos.unwrap().filter_map(|item| item.ok()).collect();
        infos
    }
    pub fn query(&self, query: &str,separator:&str , header_decorator:bool) {
        let mut stmt = self
            .conn
            .prepare(query)
            .expect(&format!("{}:失败!!", query));
        let names = stmt.column_names();
        for (i, name) in names.iter().enumerate() {
            if i > 0 {
                print!("{}",separator);
            }
            print!("{}", name);
        }
        println!("");
        let len = names.len();
        if header_decorator {
           println!("{}","-".repeat(len*4)) ;
        }
        let infos = stmt
            .query_map([], |row| {
                let mut i = 0;
                let mut info = String::new();
                loop {
                    if len <= i {
                        break;
                    } else if i > 0 {
                        info.push_str(separator);
                    }
                    let filed = row.get_ref(i);
                    match filed {
                        // Ok(a) => info.push_str(&a),
                        Ok(e) => {
                            match e.data_type() {
                                rusqlite::types::Type::Null => {
                                    // info.push_str(&"");
                                }
                                rusqlite::types::Type::Text => {
                                    info.push_str(&e.as_str()?);
                                }
                                rusqlite::types::Type::Integer => {
                                    info.push_str(&e.as_i64()?.to_string());
                                }
                                rusqlite::types::Type::Real => {
                                    info.push_str(&e.as_f64()?.to_string());
                                }
                                rusqlite::types::Type::Blob => {
                                    let mut buffer = String::new();
                                    let _ = e.as_blob()?.read_to_string(&mut buffer);
                                    info.push_str(&buffer);
                                }
                            }
                        }
                        Err(e) => {
                            panic!("{}", e);
                        }
                    }
                    i = i + 1;
                }
                return Ok(info);
            })
            .unwrap();
        for info in infos {
            println!("{}", info.unwrap());
        }
    }
}
#[derive(Debug)]
pub struct TableInfo {
    pub name: String,
    pub tbl_name: String,
    pub sql: String,
}
impl Display for TableInfo {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f,"{}\t{}的结构:\n{}",self.name,self.tbl_name,self.sql)
    }
}